home *** CD-ROM | disk | FTP | other *** search
/ Almathera Ten Pack 3: CDPD 3 / Almathera Ten on Ten - Disc 3: CDPD3.iso / ab20 / ab20_archive / utilities / emulators / unixlib.lzh / socket.c < prev   
C/C++ Source or Header  |  1991-10-22  |  11KB  |  482 lines

  1. #include <sys/types.h>
  2. #include <sys/socket.h>
  3. #include <netdb.h>
  4. #include <netinet/in.h>
  5.  
  6. #include <exec/types.h>
  7. #include <exec/ports.h>
  8.  
  9. #include <stdio.h>
  10. #include <errno.h>
  11. #include <functions.h>
  12.  
  13. extern int errno;
  14. char *malloc();
  15.  
  16. #define MAXSOCKET 20
  17.  
  18. static struct socket_entry {
  19.     int in_use;
  20.     char *to_client;
  21.     char *from_client;
  22.     } sockets[MAXSOCKET];
  23.  
  24. /* this structs must be used by telnet too */
  25. struct connect_message {
  26.     struct Message Msg;
  27.     char *port_name;
  28. };
  29.  
  30. struct data_message {
  31.     struct Message Msg;
  32.     char *buffer;
  33.     int length;
  34. };
  35.  
  36.  
  37. extern char *mktemp(char *);
  38.  
  39. /* For more info about this functions, consult an UNIX-manual */
  40. int sowrite(int, char *, int);
  41. int soread(int, char *, int);
  42. int accept(int, struct sockaddr *, int *);
  43. int socket( int, int, int);
  44. int find_free_socket(void);
  45. void soclose(int);
  46. int setsockopt(int, int, int, char *, int);
  47. int bind(int, struct sockaddr *, int);
  48.  
  49. int SafePutToPort(struct Message *, char *);
  50. struct Message *SafeReadFromPort(char *);
  51.  
  52.  
  53. /* functions which handle fd_sets are macro's, defined in sys/types.h
  54. #define    FD_SET(n, p)    ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS)))
  55. #define    FD_CLR(n, p)    ((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS)))
  56. #define    FD_ISSET(n, p)    ((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS)))
  57. #define    FD_ZERO(p)    bzero((char *)(p), sizeof (*(p)))
  58. */
  59.  
  60. void add_signal_to_fdset(n, p)
  61.     int n;
  62.     fd_set *p;
  63. {
  64.     register char *portname;
  65.     register struct MsgPort *port;
  66.  
  67.     if(!sockets[n].in_use)
  68.     return;
  69.     if(!(portname = sockets[n].from_client))
  70.     return;
  71.     if(!(port = FindPort(portname)))
  72.     return;
  73.     *p = *p | 1 << port->mp_SigBit;
  74.     return;
  75. }
  76.  
  77.  
  78. void delete_signal_from_fdset(n, p)
  79.     int n;
  80.     fd_set *p;
  81. {
  82.     char *portname;
  83.     struct MsgPort *port;
  84.     ULONG signal;
  85.  
  86.     fprintf(stderr, "FD_CLR\n");
  87.     if(!sockets[n].in_use) {
  88.     fprintf(stderr, "signal from unused socket %d taken\n", n);
  89.     return;
  90.     }
  91.     if(!(portname = sockets[n].from_client)) {
  92.     fprintf(stderr, "socket %d has no from_client port !\n",n);
  93.     return;
  94.     }
  95.     fprintf(stderr, "%s\n", portname);
  96.     if(!(port = FindPort(portname))) {
  97.     fprintf(stderr, "Could not find port %s\n", portname);
  98.     return;
  99.     }
  100.     signal = 1 << port->mp_SigBit;
  101.     fprintf(stderr, "signal(hex): %x\n", signal);
  102.     fprintf(stderr, "fdset (hex): %x\n", *p);
  103.  
  104.     *p = (*p) & (~signal);
  105.     fprintf(stderr, "fdset (hex): %x\n", *p);
  106.     return;
  107. }
  108.  
  109. int is_member_of_fdset(n, p)
  110.     int n;
  111.     register fd_set *p;
  112. {
  113.     register char *portname;
  114.     register struct MsgPort *port;
  115.     register ULONG signal;
  116.     register int result;
  117.  
  118.     if(!sockets[n].in_use) {
  119.     fprintf(stderr, "signal from unused socket %d taken\n", n);
  120.     return 0;
  121.     }
  122.     if(!(portname = sockets[n].from_client)) {
  123.     fprintf(stderr, "socket %d has no from_client port !\n",n);
  124.     return 0;
  125.     }
  126.     if(!(port = FindPort(portname))) {
  127.     fprintf(stderr, "Could not find port %s\n", portname);
  128.     return 0;
  129.     }
  130.     signal = 1 << port->mp_SigBit;
  131.     result = (*p) & signal;
  132.  
  133.     return (result!=0);
  134. }
  135.  
  136.  
  137. shutdown(socket, number)
  138.     register int socket;
  139.     register int number;
  140. {
  141.     char tmp[4];
  142.  
  143.     tmp[0] = -1;
  144.     tmp[1] = -3;
  145.     tmp[2] =  1;
  146.     tmp[3] =  '\0';
  147.     sowrite(socket, tmp, 3);
  148. }
  149.  
  150.  
  151. /* sowrite will write to the clientport
  152.  * the client must read from the clientport, and write to the serverport
  153.  * When we write a message to the other side, we wait for the reply
  154.  */
  155. int sowrite(socket, buffer, length)
  156.     int socket, length;
  157.     char *buffer;
  158. {
  159.     register struct data_message *msg;
  160.     register struct MsgPort *waitport;
  161.     register ULONG signal;
  162.     register int i;
  163.  
  164.     waitport = CreatePort(NULL, 0);
  165.     if(!waitport) {
  166.     fprintf(stderr, "Could not allocate waitport\n");
  167.     errno = EIO;
  168.     return -1;
  169.     }
  170.     if(!(msg = (struct data_message *) malloc(sizeof (struct data_message)) )) {
  171.     fprintf(stderr, "Could not allocate message\n");
  172.     errno = EIO;
  173.     return -1;
  174.     }
  175.     msg->Msg.mn_Node.ln_Type = NT_MESSAGE;
  176.     msg->Msg.mn_Length = sizeof(struct data_message);
  177.     msg->Msg.mn_ReplyPort = waitport;
  178.  
  179.     msg->buffer = buffer;
  180.     msg->length = length;
  181.  
  182.     if(!SafePutToPort( (struct Message*)msg, sockets[socket].to_client)) {
  183.     fprintf(stderr,"Could not find client-port\n");
  184.     errno = EIO;
  185.     length = -1;
  186.     }
  187.     else
  188.     {
  189.     signal = Wait( SIGBREAKF_CTRL_D | 1L << waitport->mp_SigBit);
  190.     if(signal & SIGBREAKF_CTRL_D ) {
  191.         errno = EIO;
  192.         fprintf(stderr, "sowrite : aborted waiting for reply\n");
  193.         DeletePort(waitport);
  194.         return -1;
  195.         }
  196.     errno = 0;        /* NO ERROR */
  197.     }
  198.     free((char*) msg);
  199.     DeletePort(waitport);
  200.     return length;
  201. }
  202.  
  203.  
  204. int soread(socket, buffer, length)
  205.     int socket, length;
  206.     char *buffer;
  207. {
  208.     register struct data_message *msg = NULL;
  209.     register struct MsgPort *port = NULL;
  210.     register int bufpos = 0;    /* first free position in the buffer */
  211.     register int i,x;
  212.  
  213.     /* If we get here, there must be a message
  214.      */
  215.  
  216.      if(!(port = FindPort(sockets[socket].from_client))) {
  217.     fprintf(stderr,"Could not find the port\n");
  218.     errno = EHOSTUNREACH;
  219.     return -1;
  220.     }
  221.  
  222.     /* Yes, read the port !! */
  223.     while( msg = (struct data_message*) SafeReadFromPort(sockets[socket].from_client))
  224.     { /* concatenate the received message to the buffer */
  225.     for(i=0;i<msg->length;i++)
  226.         buffer[bufpos+i] = msg->buffer[i];
  227.  
  228.     ReplyMsg((struct Message *)msg);   /* tell telnet we received it */
  229.     bufpos = bufpos+i;
  230.     }
  231.     if(bufpos == 0) {
  232.     fprintf(stderr, "soread : could not read any message !!\n");
  233.     errno = EMSGSIZE;
  234.     return -1;
  235.     }
  236.     return bufpos;
  237. }
  238.  
  239. int accept(s, addr, addrlen)
  240.     int s;
  241.     struct sockaddr *addr;
  242.     int *addrlen;
  243. {
  244.     register struct MsgPort *port;
  245.     register struct connect_message *msg;
  246.     register int new_socket;
  247.     register char *to_client;
  248.     register ULONG signal;
  249.  
  250.     /* copy socket s to a new socket, and return the descriptor for the
  251.      * new socket-descriptor and fill in the addr en addrlen fields
  252.      */
  253.     if(!sockets[s].in_use) {
  254.     fprintf(stderr, "socket %d is not in use !!!\n", s);
  255.         errno = EINTR;
  256.         return -1;
  257.         }
  258.  
  259.     if(!(port = FindPort(sockets[s].from_client))) {
  260.     fprintf(stderr, "Could not find port\n");
  261.     return -1;
  262.     }
  263.  
  264.     /* Allow 1 client, let the rest wait */
  265.     msg = (struct connect_message *) SafeReadFromPort(sockets[s].from_client);
  266.     if(!msg) {
  267.         errno = EWOULDBLOCK;
  268.         return -1;
  269.     }
  270.     new_socket = socket(0,0,0);
  271.     if(new_socket == -1) {
  272.     msg->port_name = NULL;
  273.         ReplyMsg((struct Message *)msg);
  274.         return -1;
  275.         }
  276.  
  277. /* store the port to which we must send data */
  278.     to_client = malloc(strlen(msg->port_name)+1);
  279.     strcpy(to_client, msg->port_name);
  280.     sockets[new_socket].to_client = to_client;
  281.  
  282. /* return the port to which we will listen */
  283.     msg->port_name = sockets[new_socket].from_client;
  284.  
  285.     ReplyMsg((struct Message *) msg);
  286.     return new_socket;
  287. }
  288.  
  289.  
  290. int socket( domain, type, protocol)
  291.     int domain, type, protocol;
  292. {
  293.     register struct MsgPort *port;
  294.     register int new_sd;
  295.     register char *name, *tmpname;
  296.  
  297. /* this code does not need Forbid()/Permit(), when you want to run 2 mud's,
  298.    you should add it :+)
  299.  */
  300.     tmpname = mktemp("parserXXXXXXXX");
  301.     name = malloc(strlen(tmpname) + 1);
  302.     strcpy(name, tmpname);
  303.  
  304.     if(!name) {
  305.     fprintf(stderr, "Could not create new port name\n");
  306.     return -1;
  307.     }
  308.     new_sd = find_free_socket();
  309.     if(new_sd == -1) {
  310.         errno = EMFILE;
  311.         return -1;
  312.         }
  313.     if((port = (struct MsgPort *) CreatePort(name, 0)) == NULL) {
  314.         errno = ENOBUFS;
  315.         return -1;
  316.         }
  317.     sockets[new_sd].from_client = name;    /* we will listen to this name */
  318.     sockets[new_sd].to_client   = NULL;    /* will be filled in by accept() */
  319.     sockets[new_sd].in_use      = 1;
  320.  
  321.     return new_sd;
  322. }
  323.  
  324.  
  325. int find_free_socket()
  326. {
  327.     register int entry = MAXSOCKET-1;
  328.     while(entry >= 0) {
  329.         if(sockets[entry].in_use == 0)
  330.              return entry;
  331.         entry--;
  332.     }
  333.     return -1;
  334. }
  335.  
  336.  
  337. void soclose(socket)
  338.     int socket;
  339. {
  340.     register struct MsgPort *port;
  341.  
  342.     /* I should check that this was the last reference to the socket */
  343.     if(socket < 0 || socket >= MAXSOCKET) {
  344.     fprintf(stderr, "failed to close socket %d\n", socket);
  345.     return;
  346.     }
  347.     if(!sockets[socket].in_use) {
  348.     fprintf(stderr, "failed to close socket %d\n", socket);
  349.     return;
  350.     }
  351.     port = FindPort(sockets[socket].from_client);
  352.     if(!port) {
  353.     fprintf(stderr,"tried to close non-existing port\n");
  354.     return;
  355.     }
  356.     DeletePort(port);
  357.  
  358.     if(sockets[socket].from_client)
  359.     free(sockets[socket].from_client);
  360.     if(sockets[socket].to_client)
  361.     free(sockets[socket].to_client);
  362.  
  363.     sockets[socket].from_client = NULL;
  364.     sockets[socket].to_client = NULL;
  365.     sockets[socket].in_use = 0;
  366. }
  367.  
  368.  
  369. int setsockopt(s, level, optname, optval, optlen)
  370.     int s, level, optname;
  371.     char *optval;
  372.     int optlen;
  373. {
  374.     return 0;
  375. }
  376.  
  377.  
  378. int bind(s, name, namelen)
  379.     int s;
  380.     struct sockaddr *name;
  381.     int namelen;
  382. {
  383.     register struct MsgPort *old_port, *new_port;
  384.     register char *port_name;
  385.  
  386.     /* according to the manual, socket s should have no name yet, but
  387.      * it should get the name specified in name. So lets remove the old
  388.      * name, and replace it with a new one. The portname is specified as
  389.      * an unsigned int, but let's pretend it is a 32 bits number. We need
  390.      * 10 + 1 digits in the string, let's make that 20 and hope it's enough
  391.      */
  392.     port_name = malloc(20);
  393.     sprintf(port_name, "%u", ((struct sockaddr_in *)name)->sin_port);
  394.  
  395.     if(!sockets[s].in_use) {/* trying to bind a socket that's not in use */
  396.     fprintf(stderr, "Can't bind a free socket !\n");
  397.     return -1;
  398.     }
  399.     old_port = FindPort(sockets[s].from_client);
  400.     if(!old_port) {
  401.     fprintf(stderr, "Non-existing port\n");
  402.     return -1;
  403.     }
  404.  
  405.     if(FindPort((char*)port_name) != NULL) { /* Each name must be unique */
  406.     fprintf(stderr, "Name must be unique\n");
  407.         errno = EADDRINUSE;
  408.         return -1;
  409.         }
  410.  
  411. /* Delete the old port, and create a new port with a name, no
  412.    checking for messages, cos I did not send any
  413.  */
  414.     new_port = CreatePort(port_name,0);
  415.     if(!new_port) {
  416.     fprintf(stderr, "failed to create new socket\n");
  417.     return -1;
  418.     }
  419.     /* delete the old port */
  420.     soclose(s);
  421.  
  422.     sockets[s].from_client = port_name;
  423.     sockets[s].to_client = NULL;    /* no replyport !! */
  424.     sockets[s].in_use = 1;
  425.  
  426.     return 0;
  427. }
  428.  
  429.  
  430. int listen(s, backlog)
  431.     int s, backlog;
  432. {
  433.     return 0;
  434. }
  435.  
  436.  
  437. int SafePutToPort(message, portname)
  438.     struct Message *message;
  439.     char * portname;
  440. {
  441.     register struct MsgPort *port;
  442.  
  443.     Forbid();
  444.     port = FindPort(portname);
  445.     if(port)
  446.     PutMsg(port, message);
  447.     Permit();
  448.     if(port) {
  449.     errno = 0;
  450.     return 1;
  451.     }
  452.     else
  453.     {
  454.     errno = EIO;
  455.     return 0;
  456.     }
  457. }
  458.  
  459.  
  460. struct Message *SafeReadFromPort(portname)
  461.     char * portname;
  462. {
  463.     register struct MsgPort *port;
  464.     register struct Message *msg;
  465.  
  466.     Forbid();
  467.     port = FindPort(portname);
  468.     if(port)
  469.     msg = GetMsg(port);
  470.     Permit();
  471.     if(port)
  472.     {
  473.     errno = 0;
  474.     return msg;
  475.     }
  476.     else
  477.     {
  478.     errno = EIO;
  479.     return NULL;
  480.     }
  481. }
  482.